package framework.base;

import tk.mybatis.mapper.util.StringUtil;

import javax.persistence.Column;
import javax.persistence.Table;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.stream.Collectors;

public class UpdateObjectProvider {
    private static final ConcurrentHashMap<Class<?>, List<Field>> FIELD_CACHE = new ConcurrentHashMap<>();

    protected List<Field> loadField(Class<?> objClass) {
        return FIELD_CACHE.computeIfAbsent(
                objClass,
                clazz -> Arrays.stream(clazz.getDeclaredFields())
                        .filter(f -> {
                            try {
                                // 检查是否存在公共getter方法
                                String getterName = "get" + f.getName().substring(0, 1).toUpperCase() + f.getName().substring(1);
                                Method getter = clazz.getMethod(getterName);
                                return Modifier.isPublic(getter.getModifiers());
                            } catch (NoSuchMethodException e) {
                                return false;
                            }
                        })
                        .peek(f -> f.setAccessible(true))
                        .collect(Collectors.toList())
        );
    }

    public String updateObject(Map map) {
        Object obj = map.get("obj");
        Object where = map.get("where");

        // 获取表名（通过 @Table 注解）
        Table tableAnnotation = obj.getClass().getAnnotation(Table.class);
        if (tableAnnotation == null) {
            throw new IllegalArgumentException(obj.getClass().getName() + " not apply @Table");
        }
        String tableName = tableAnnotation.name();

        // 从缓存获取字段列表（若不存在则反射获取并缓存）
        List<Field> fields = loadField(obj.getClass());

        // 动态生成 SQL
        StringBuilder sql = new StringBuilder("UPDATE " + tableName + " SET ");
        for (Field field : fields) {
            String fieldName = field.getName();
            if (!"id".equals(fieldName)) {
                Column column = field.getAnnotation(Column.class);
                String dbFieldName = column != null ? column.name() :
                        // 驼峰转下划线
                        StringUtil.camelhumpToUnderline(fieldName);
                sql.append(dbFieldName).append("=#{obj.").append(fieldName).append("}, ");
            }
        }
        // 删除最后的 ", "
        sql.delete(sql.length() - 2, sql.length());

        //
        fields = loadField(where.getClass());
        StringBuilder wsql = new StringBuilder();
        for (Field field : fields) {
            Object value;
            try {
                value = field.get(where);
            } catch (IllegalAccessException e) {
                value = null;
            }
            if (value != null) {
                String fieldName = field.getName();
                Column column = field.getAnnotation(Column.class);
                String dbFieldName = column != null ? column.name() :
                        // 驼峰转下划线
                        StringUtil.camelhumpToUnderline(fieldName);
                wsql.append(dbFieldName).append("=#{where.").append(fieldName).append("} AND ");
            }
        }

        //
        if (wsql.length() == 0) {
            throw new IllegalArgumentException("Not set query where condition");
        }

        //
        sql.append(" WHERE ").append(wsql.delete(wsql.length() - 5, wsql.length()));
        return sql.toString();
    }

    public String updateObjectById(Map map) {
        Object obj = map.get("obj");

        // 获取表名（通过 @Table 注解）
        Table tableAnnotation = obj.getClass().getAnnotation(Table.class);
        if (tableAnnotation == null) {
            throw new IllegalArgumentException(obj.getClass().getName() + " not apply @Table");
        }
        String tableName = tableAnnotation.name();

        // 从缓存获取字段列表（若不存在则反射获取并缓存）
        List<Field> fields = loadField(obj.getClass());

        // 动态生成 SQL
        StringBuilder sql = new StringBuilder("UPDATE " + tableName + " SET ");
        StringBuilder wsql = new StringBuilder();
        for (Field field : fields) {
            String fieldName = field.getName();
            Column column = field.getAnnotation(Column.class);
            String dbFieldName = column != null ? column.name() :
                    // 驼峰转下划线
                    StringUtil.camelhumpToUnderline(fieldName);
            if ("id".equals(fieldName)) {
                wsql.append(dbFieldName).append("=#{obj.").append(fieldName).append("} AND ");
            } else {
                sql.append(dbFieldName).append("=#{obj.").append(fieldName).append("}, ");
            }
        }
        // 删除最后的 ", "
        sql.delete(sql.length() - 2, sql.length());

        // 删除最后的 " AND "
        if (wsql.length() == 0) {
            throw new IllegalArgumentException("id field not found in " + obj.getClass().getName());
        }

        //
        sql.append(" WHERE ").append(wsql.delete(wsql.length() - 5, wsql.length()));
        return sql.toString();
    }
}
